﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
using System.Windows;

namespace ConfigCreate
{
    /// <summary>
    /// 数据模板管理类
    /// </summary>
    public class DataTemplateManager
    {
        internal static bool IsRegistered = false;
        internal static Dictionary<object, object> RegList = new Dictionary<object, object>();

        /// <summary>
        /// 对View和ViewModel进行注册绑定。设置自定义控件时设置ViewModel对象即可自动生成View控件
        /// </summary>
        /// <typeparam name="TViewModel">ViewModel类型</typeparam>
        /// <typeparam name="TView">View控件类型</typeparam>
        public static void RegisterDataTemplate<TViewModel, TView>() where TView : FrameworkElement
        {
            RegisterDataTemplate(typeof(TViewModel), typeof(TView));
        }

        /// <summary>
        /// 对View和ViewModel进行注册绑定。设置自定义控件时设置ViewModel对象即可自动生成View控件
        /// </summary>
        /// <param name="viewModelType">ViewModel类型</param>
        /// <param name="viewType">View控件类型</param>
        public static void RegisterDataTemplate(Type viewModelType, Type viewType)
        {
            var template = CreateTemplate(viewModelType, viewType);
            var key = template.DataTemplateKey;
            if (System.Windows.Application.Current != null)
            {
                System.Windows.Application.Current.Resources.Add(key, template);
                IsRegistered = true;
            }
            else
            {
                RegList.Add(key, template);
            }
        }

        private static DataTemplate CreateTemplate(Type viewModelType, Type viewType)
        {
            const string xamlTemplate = "<DataTemplate DataType=\"{{x:Type vm:{0}}}\"><v:{1} /></DataTemplate>";
            var xaml = String.Format(xamlTemplate, viewModelType.Name, viewType.Name, viewModelType.Namespace, viewType.Namespace);

            var context = new ParserContext();

            context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
            context.XamlTypeMapper.AddMappingProcessingInstruction("vm", viewModelType.Namespace, viewModelType.Assembly.FullName);
            context.XamlTypeMapper.AddMappingProcessingInstruction("v", viewType.Namespace, viewType.Assembly.FullName);

            context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            context.XmlnsDictionary.Add("vm", "vm");
            context.XmlnsDictionary.Add("v", "v");

            var template = (DataTemplate)XamlReader.Parse(xaml, context);
            return template;
        }
    }
}
